package cn.edu.neu.softlab.jason.offer.jianzhioffer.datastructure;

import cn.edu.neu.softlab.jason.offer.jianzhioffer.datastructure.functions.Mianshi14Fun1;
import cn.edu.neu.softlab.jason.offer.jianzhioffer.datastructure.interfaces.Mianshi14Interface;

/**
 * 剑指offer-面试14
 * 调整整数数组顺序使奇数位于偶数前面
 * 输入一个整数数组，实现一个函数调整该数组中数组的顺序，是的所有奇数位于
 * 数组的前半部分，而所有偶数位于数组的后半部分。
 */
public class Mianshi14 {
    public static void main(String[] args) throws Exception {
        int[] array = {1, 2, 3, 4, 5, 6};
//        reformatArrayOffer1(array);
        // 接口的实现方式
//        Mianshi14Interface fun = new Mianshi14Fun1();
//        reformArrayWithInterface(array, fun);
        // lambda 表达式
        reformArrayWithInterface(array, (value) -> (value & 1) == 0);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
    }

    public static void reformatArray(int[] array) throws Exception {
        reformatArrayRecursively(array, 0, array.length - 1);
    }

    public static void reformatArray1(int[] array) {
        int sflag = 0;
        int eflag = array.length - 1;
        while (true) {
            for (int i = sflag; i < eflag; i++) {
                if ((array[i] & 1) == 0) {
                    sflag = i;
                    break;
                }
            }
            for (int i = eflag; i > sflag; i--) {
                if ((array[i] & 1) == 1) {
                    eflag = i;
                    break;
                }

            }
            if (eflag <= sflag || (array[sflag] & 1) != 0 || (array[eflag] & 1) == 0) {
                break;
            } else {
                int tmp = array[eflag];
                array[eflag] = array[sflag];
                array[sflag] = tmp;
            }
        }
    }

    public static void reformatArrayOffer1(int[] array) throws Exception {
        if (array == null) {
            throw new Exception("空数组");
        }
        int sflag = 0;
        int eflag = array.length - 1;
        while (sflag < eflag) {
            while (sflag < eflag && (array[sflag] & 1) == 1) {
                sflag++;
            }
            while (sflag < eflag && (array[eflag] & 1) == 0) {
                eflag--;
            }
            if (sflag < eflag) {
                int tmp = array[sflag];
                array[sflag] = array[eflag];
                array[eflag] = tmp;
            }
        }
    }

    /**
     * java 把函数作为参数传递进来，第一种方法，接口的方法实现；第二种，java动态代理；第三种，java8中的lambda表达式
     * 下面分别用这二种种方式进行扩展。
     */

    // 接口的实现方式
    public static void reformArrayWithInterface(int[] array, Mianshi14Interface fun) throws Exception {
        if (array == null) {
            throw new Exception("空数组");
        }
        int sflag = 0;
        int eflag = array.length - 1;
        while (sflag < eflag) {
            while (sflag < eflag && !fun.func(array[sflag])) {
                sflag++;
            }
            while (sflag < eflag && fun.func(array[eflag])) {
                eflag--;
            }
            if (sflag < eflag) {
                int tmp = array[sflag];
                array[sflag] = array[eflag];
                array[eflag] = tmp;
            }
        }
    }

    // java8 lambda表达式

    private static void reformatArrayRecursively(int[] array, int start, int end) throws Exception {
        if (array == null || start < 0 || end >= array.length) {
            throw new Exception("数组为空或者参数cuowu");
        }
        if (start >= end) {
            return;
        }
        int sflag = -1;
        int eflag = -1;
        for (int i = start; i < end; i++) {
            if ((array[i] & 1) == 0) {
                sflag = i;
                break;
            }
        }
        if (sflag < end) {
            for (int i = end; i > sflag && i > start; i--) {
                if ((array[i] & 1) == 1) {
                    eflag = i;
                    break;
                }
            }
        }
        if (sflag != -1 && eflag != -1) {
            int tmp = array[sflag];
            array[sflag] = array[eflag];
            array[eflag] = tmp;
            reformatArrayRecursively(array, sflag, eflag);
        }
        return;
    }
}
